import org.apache.spark.graphx.{Graph, VertexId, Edge}
import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}

// 定义一个Person样例类
case class Person(name: String, age: Int)

object ConnectComponentsExample {
    def main(args: Array[String]): Unit = {
        var conf = new SparkConf().setAppName("ConnectComponentsExample").setMaster("local[*]")
        var sc = new SparkContext(conf)
        
        // 创建顶点RDD
        var vertices: RDD[(VertexId, Person)] = sc.parallelize(Seq(
            (1L, Person("Alice", 20)),
            (2L, Person("Bob", 18)),
            (3L, Person("Charlie", 30)),
            (4L, Person("Dave", 25)),
            (5L, Person("Eve", 30))
        ))
        
        // 在一个图（Graph）中，连通分量是指图中的一个极大连通子图。
        // "极大"是定义中的关键点。它意味着这个连通子图是“尽可能大”的。
        // 你不能再向这个子图中添加原图中的任何一个额外的顶点（以及与之相关的边）而不破坏它的连通性。
        // 换句话说，这个子图包含了所有能通过路径到达该子图中任何一个顶点的顶点。
        // 简单来说连通分量是图中的一个“独立部分”，在这个部分内部，所有顶点都是相互可达的（对于无向图或
        // 弱连通的有向图），或者任意两点互相可达（对于强连通分量）。
        // 这个“独立部分”是完整的，你无法在不破坏其内部连通性的前提下把图的其他顶点加进来。
        // 一个图可以由一个或多个这样的连通分量组成。
        
        // 创建边RDD
        var edges: RDD[Edge[String]] = sc.parallelize(Seq(
            Edge(1L, 2L, "friend"),
            Edge(2L, 3L, "colleague"),  // 注释这一行断开连接后，就有两个极大连通子图。
            Edge(3L, 4L, "friend"),
            Edge(4L, 5L, "colleague")
        ))
        
        // 创建图
        var graph = Graph(vertices, edges)
        
        // 计算连通分量
        var cc = graph.connectedComponents()
        
        // 打印结果
        cc.vertices.collect().foreach {
            case (id, ccId) => 
                println(s"Vertex $id is in connected component $ccId")
        }
    }
}

// cd ....build.sbt的目录....
// sbt run
